package com.fyx.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fyx.config.FiveMongoConfig;
import com.fyx.config.FourthMongoConfig;
import com.fyx.config.RequestConfig;
import com.fyx.config.SecondaryMongoConfig;
import com.fyx.entity.*;
import com.fyx.mapper.LostGoldMapper;
import com.fyx.mapper.SysDictDetailMapper;
import com.fyx.mapper.SysUserMapper;
import com.fyx.service.IPayService;
import com.fyx.until.DateUtil;
import com.fyx.until.HttpUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.SkipOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

import static org.springframework.data.mongodb.core.aggregation.Aggregation.match;

@Service
public class PayServiceImpl extends ServiceImpl<SysUserMapper, SysUser>  implements IPayService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Resource(name = FourthMongoConfig.MONGO_TEMPLATE)
    private MongoTemplate fourthMongoTemplate;

    @Resource(name = FiveMongoConfig.MONGO_TEMPLATE)
    private MongoTemplate fiveMongoTemplate;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private LostGoldMapper lostGoldMapper;

    @Override
    public Map address(SysUser sysUser, Pageable pageable) {
        Page<SysUser> page = new Page<>(pageable.getPageNumber()+1,pageable.getPageSize());
        IPage<SysUser> ipage = sysUserMapper.getAddressList(page,sysUser.getUserId());
        List<SysUser> list = ipage.getRecords();
        long total = ipage.getTotal();
        Map map =new HashMap();
        map.put("list",list);
        map.put("total",total);
        return map;
    }

    @Override
    public Map abnormalOrders(AbnormalOrdersEntity abnormalOrdersEntity, Pageable pageable) {
        List<AbnormalOrdersEntity> list = new ArrayList<>();
        long total = 0l;
        Criteria criteria=new Criteria();
        Query query=new Query();
        query.skip((pageable.getPageNumber())*pageable.getPageSize());
        query.limit(pageable.getPageSize());
        if(abnormalOrdersEntity.getPid()!=null){
            criteria.and("pid").is(abnormalOrdersEntity.getPid());
        }
        if(abnormalOrdersEntity.getOut_trade_no()!=null){
            criteria.and("out_trade_no").is(abnormalOrdersEntity.getOut_trade_no());
        }
        query.with( Sort.by(Sort.Direction.DESC,new String[]{"time"}));
        if(abnormalOrdersEntity.getPid()!=null||abnormalOrdersEntity.getOut_trade_no()!=null){
            criteria.and("content").exists(true);
            query.addCriteria(criteria);
            if(abnormalOrdersEntity.getFlag()!=null&&abnormalOrdersEntity.getFlag().equals("totalcl")){
                list = fiveMongoTemplate.find(query, AbnormalOrdersEntity.class, "pre_order");
                total = fiveMongoTemplate.count(query, AbnormalOrdersEntity.class, "pre_order");
            }else {
                list = mongoTemplate.find(query, AbnormalOrdersEntity.class, "pre_order");
                total = mongoTemplate.count(query, AbnormalOrdersEntity.class, "pre_order");
            }
        }
        Map map2 =new HashMap();
        map2.put("content",list);
        map2.put("totalElements",total);
        return map2;
    }

    @Override
    public Map abnormalOrders1(AbnormalOrdersEntity abnormalOrdersEntity, Pageable pageable) {
        //超时补单
        List<AbnormalOrdersEntity> list = new ArrayList<>();
        JSONObject jsonObject2 = new JSONObject();
//            jsonObject2.put("pid",abnormalOrdersEntity.getPid());
//            jsonObject2.put("time",abnormalOrdersEntity.getTime()/1000);
        JSONObject map1 = new JSONObject();
        map1.put("cmd","timeout_order");
        map1.put("args",jsonObject2);
        JSONObject jsonObject3 = new JSONObject();
        try {
            jsonObject3=JSONObject.parseObject(HttpUtil.post(RequestConfig.baseRequestUrl1, map1.toJSONString(),"utf-8"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        JSONArray jSONArray1= new JSONArray();
        String str=JSON.toJSONString(jsonObject3.get("orders"));
        if(!str.equals("{}")){
            jSONArray1 = (JSONArray) jsonObject3.get("orders");
            list =jSONArray1.toJavaList(AbnormalOrdersEntity.class);
        }

        Map map2 =new HashMap();
        map2.put("content",list);
        map2.put("totalElements",list.size());
        return map2;
    }

    @Override
    public String appleBudan(AbnormalOrdersEntity abnormalOrdersEntity) {
        String result="false";
        if((abnormalOrdersEntity.getTime()+1800)<new Date().getTime()/1000) {
            if(abnormalOrdersEntity.getContent().size()>0) {
                UserEntity userEntity = mongoTemplate.findOne(new Query().addCriteria(Criteria.where("userid").is(abnormalOrdersEntity.getPid())), UserEntity.class, "user");
                OrderEntity orderEntity = new OrderEntity();
                orderEntity.setPid(abnormalOrdersEntity.getPid());
                orderEntity.setChannel(userEntity.getChannel());
                orderEntity.setOs(abnormalOrdersEntity.getOs());
                orderEntity.setOut_trade_no(abnormalOrdersEntity.getOut_trade_no());
                orderEntity.setTime_end((int)(new Date().getTime()/1000));
                orderEntity.setTotal_fee(abnormalOrdersEntity.getPrice().intValue());
                orderEntity.setMall_id(abnormalOrdersEntity.getMall_id());
                orderEntity.setPlatform(abnormalOrdersEntity.getPlatform());
                fourthMongoTemplate.insert(orderEntity);
                Update update=new Update();
                update.set("status",1001);
                fourthMongoTemplate.updateFirst(new Query().addCriteria(Criteria.where("_id").is(abnormalOrdersEntity.get_id())),update,"pre_order");
                Thread t = new Thread(new Runnable() {
                    public void run() {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("p_id", orderEntity.getPid());
                        jsonObject.put("title", "补单");
                        jsonObject.put("content", "补单" + abnormalOrdersEntity.getName());
                        jsonObject.put("mail_type", 3);
                        jsonObject.put("award", abnormalOrdersEntity.getContent());
                        JSONObject map = new JSONObject();
                        map.put("cmd", "send_mail");
                        map.put("args", jsonObject);
                        try {
                            HttpUtil.post(RequestConfig.baseRequestUrl, map.toJSONString(), "utf-8");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
                t.start();
                result = "true";
            }
        }
        return result;
    }

    @Override
    public String timeOutBudan(AbnormalOrdersEntity abnormalOrdersEntity) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("out_trade_no",abnormalOrdersEntity.getOut_trade_no());
        JSONObject map = new JSONObject();
        map.put("cmd","try_timeout_order");
        map.put("args",jsonObject);
        String result=null;
        try {
            result= HttpUtil.post(RequestConfig.baseRequestUrl1, map.toJSONString(),"utf-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    @Autowired
    private SysDictDetailMapper sysDictDetailMapper;


    public List<SysDictDetail> getDictId(long dictId){
        QueryWrapper<SysDictDetail> wrapper=new QueryWrapper<>();
        wrapper.eq("dict_id",dictId);
        List<SysDictDetail> list =sysDictDetailMapper.selectList(wrapper);
        return list;
    }

    @Override
    public Map rechargeCount(OrderEntity orderEntity, Pageable pageable) {
        List<SysDictDetail> propsDictDictList =getDictId(15);
        Map propsDictMap = new HashMap();
        for(SysDictDetail sysDictDetail:propsDictDictList){
            propsDictMap.put(sysDictDetail.getValue(),sysDictDetail.getLabel());
        }

        Criteria criteria = new Criteria();
        if (orderEntity.getQTime()!=null){
            criteria.andOperator(Criteria.where("time_end").gte(orderEntity.getQTime().get(0).getTime()/1000).lte(orderEntity.getQTime().get(1).getTime()/1000));
        }
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("mall_id").sum("total_fee").as("totalFee").count().as("count"),
                Aggregation.project("mall_id","totalFee","count").and("mall_id").previousOperation(),
                Aggregation.sort(Sort.Direction.ASC,new String[]{"mall_id"}),
                new SkipOperation(pageable.getPageNumber()*pageable.getPageSize()),
                Aggregation.limit(pageable.getPageSize())
        );

        AggregationResults<OrderEntity> ar = mongoTemplate.aggregate(aggregation, "order", OrderEntity.class);
        List<OrderEntity> list = ar.getMappedResults();

        aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("mall_id"),
                Aggregation.group().count().as("total")
        );
        ar = mongoTemplate.aggregate(aggregation, "order", OrderEntity.class);
        long total = 0;
        if( ar.getMappedResults().size()>0){
            total= ar.getMappedResults().get(0).getTotal();
        }


        Map map =new HashMap();
        map.put("content",list);
        map.put("totalElements",total);
        map.put("xData",propsDictMap);
        return map;
    }

    @Override
    public Map rechargeRecord(OrderEntity orderEntity, Pageable pageable) {
        Query query=new Query();
        query.skip((pageable.getPageNumber())*pageable.getPageSize());
        query.limit(pageable.getPageSize());
        Criteria criteria = new Criteria();

        if (orderEntity.getPid()!=null){
            criteria.and("pid").is(orderEntity.getPid());
        }

        if (orderEntity.getTransaction_id()!=null){
            criteria.and("transaction_id").is(orderEntity.getTransaction_id());
        }

        if (orderEntity.getOut_trade_no()!=null){
            criteria.and("out_trade_no").is(orderEntity.getOut_trade_no());
        }

        if (orderEntity.getMall_id()!=null){
            criteria.and("mall_id").is(orderEntity.getMall_id());
        }

        if (orderEntity.getPlatform()!=null){
            criteria.and("platform").is(orderEntity.getPlatform());
        }

        List<Criteria> criteriaList = new ArrayList<>();
        if(orderEntity.getTotal_fee1()!=0){
            criteriaList.add(Criteria.where("total_fee").gte(orderEntity.getTotal_fee1()*100));
        }

        if(orderEntity.getTotal_fee2()!=0){
            criteriaList.add(Criteria.where("total_fee").lte(orderEntity.getTotal_fee2()*100));
        }

        if (orderEntity.getQTime()!=null){
            criteriaList.add(Criteria.where("time_end").gte(orderEntity.getQTime().get(0).getTime()/1000).lte(orderEntity.getQTime().get(1).getTime()/1000));
        }

        Criteria arr[] = new Criteria[criteriaList.size()];
        for (int i =0;i<criteriaList.size();i++){
            arr[i] = criteriaList.get(i);
        }
        if (arr.length>0){
            criteria.andOperator(arr);
        }

        query.addCriteria(criteria);
        query.with( Sort.by(Sort.Direction.DESC,new String[]{"time_end"}));
        List<OrderEntity> list ;  long total;
        if(orderEntity.getFlag()==null||orderEntity.getFlag().equals("hzmj")){
            list = mongoTemplate.find(query, OrderEntity.class);
            total = mongoTemplate.count(query, OrderEntity.class);
        }
        else {
            list = fiveMongoTemplate.find(query, OrderEntity.class);
            total = fiveMongoTemplate.count(query, OrderEntity.class);
        }
        if(list.size()>0) {
            for (OrderEntity orderEntity1 : list) {
                orderEntity1.setTotal_fee(orderEntity1.getTotal_fee() / 100);
                List<UserEntity> userList;
                if (orderEntity.getFlag() == null || orderEntity.getFlag().equals("hzmj")) {
                    userList = mongoTemplate.find(new Query(Criteria.where("userid").is(orderEntity1.getPid())), UserEntity.class);
                } else {
                    userList = fiveMongoTemplate.find(new Query(Criteria.where("userid").is(orderEntity1.getPid())), UserEntity.class);
                }
                if (userList.size() > 0) {
                    orderEntity1.setP_nickname(userList.get(0).getNickname());
                    orderEntity1.setReg_time(userList.get(0).getReg_time());
                    orderEntity1.setAll_fee(userList.get(0).getAll_fee());
                    orderEntity1.setChannel(userList.get(0).getChannel());
                }
                if (StringUtils.isEmpty(orderEntity1.getPlatform())) {
                    orderEntity1.setPlatform("微信");
                }
            }
        }


        Map map =new HashMap();
        map.put("list",list);
        map.put("total",total);
        return map;
    }

    @Override
    public Map queryGameUserOrder(OrderEntity orderEntity, Pageable pageable) {
        Query query=new Query();
        query.skip((pageable.getPageNumber())*pageable.getPageSize());
        query.limit(pageable.getPageSize());
        Criteria criteria = new Criteria();
        long beginTime = DateUtil.getDayBegin().getTime()/1000-2*24*3600;
        long endTime = DateUtil.getDayEnd().getTime()/1000;
        if(orderEntity.getPid()!=null){
            criteria.and("pid").is(orderEntity.getPid());
        }
        if (orderEntity.getTransaction_id()!=null){
            criteria.and("transaction_id").is(orderEntity.getTransaction_id());
        }
        if (orderEntity.getOut_trade_no()!=null){
            criteria.and("out_trade_no").is(orderEntity.getOut_trade_no());
        }
        if(!CollectionUtils.isEmpty(orderEntity.getDeptIds())){
            List<Long> deptIds= new ArrayList<>(orderEntity.getDeptIds());
            List<SysUser> channels = sysUserMapper.getUserNames(deptIds);
            String channel[] = new String[channels.size()];
            for(int i=0; i<channels.size();i++){
                channel[i]=channels.get(i).getUsername();
                System.out.println("channel:=========="+channels.get(i).getUsername());
            }
            criteria.and("channel").in(channel);
        }
        query.addCriteria(criteria);
        query.with( Sort.by(Sort.Direction.DESC,new String[]{"time_end"}));
        List<OrderEntity> list = new ArrayList<>();
        long total=0;
        if(orderEntity.getPid()!=null || orderEntity.getTransaction_id()!=null || orderEntity.getOut_trade_no()!=null){
            if(orderEntity.getFlag()!=null&&orderEntity.getFlag().equals("clmj")){
                total= fiveMongoTemplate.count(query, OrderEntity.class);
                list = fiveMongoTemplate.find(query, OrderEntity.class);
            }else {
                total= mongoTemplate.count(query, OrderEntity.class);
                list = mongoTemplate.find(query, OrderEntity.class);
            }
            for (OrderEntity orderEntity1:list){
                orderEntity1.setTotal_fee(orderEntity1.getTotal_fee()/100);
                List<UserEntity> userList;
                if(orderEntity.getFlag()!=null&&orderEntity.getFlag().equals("clmj")){
                    userList = fiveMongoTemplate.find(new Query(Criteria.where("userid").is(orderEntity1.getPid())), UserEntity.class);
                }else {
                    userList = mongoTemplate.find(new Query(Criteria.where("userid").is(orderEntity1.getPid())), UserEntity.class);
                }
                if (userList.size()>0){
                    orderEntity1.setP_nickname(userList.get(0).getNickname());
                    orderEntity1.setReg_time(userList.get(0).getReg_time());
                    orderEntity1.setAll_fee(userList.get(0).getAll_fee());
                    orderEntity1.setChannel(userList.get(0).getChannel());
                }
                if (StringUtils.isEmpty(orderEntity1.getPlatform())){
                    orderEntity1.setPlatform("微信");
                }
            }
        }


        Map map =new HashMap();
        map.put("list",list);
        map.put("total",total);
        return map;
    }

    @Override
    public Map rechargeStatistics(ChannelDataEntity channelDataEntity, Pageable pageable) {
        Criteria criteria = new Criteria();
        if(channelDataEntity.getChannel()!=null){
            criteria.and("channel").is(channelDataEntity.getChannel());
        }

        if (channelDataEntity.getQTime()!=null){
            criteria.andOperator(Criteria.where("day").gte(channelDataEntity.getQTime().get(0).getTime()/1000).lte(channelDataEntity.getQTime().get(1).getTime()/1000));
        }

        if(channelDataEntity.getBeginTime()!=null&&channelDataEntity.getEndTime()!=null){
            criteria.andOperator(Criteria.where("day").gte(channelDataEntity.getBeginTime().getTime()/1000).lte(channelDataEntity.getEndTime().getTime()/1000));
        }else  if(channelDataEntity.getBeginTime()!=null){
            criteria.and("day").gte(channelDataEntity.getBeginTime().getTime()/1000);
        }else if(channelDataEntity.getEndTime()!=null){
            criteria.and("day").lte(channelDataEntity.getEndTime().getTime()/1000);
        }

        Aggregation aggregation = Aggregation.newAggregation(
                match(criteria),
                Aggregation.group("day","channel")
                        .sum("new_charge_amount").as("new_charge_amount")
                        .sum("total_charge_pnum").as("total_charge_pnum")
                        .sum("reg_num").as("reg_num")
                        .sum("first_charge_pnum").as("first_charge_pnum")
                        .sum("total_charge").as("total_charge")
                        .sum("charge_pnum").as("charge_pnum")
                        .sum("new_charge_pnum").as("new_charge_pnum")
                        .sum("charge_amount").as("charge_amount")
                        .sum("act_num").as("act_num")
                        .first("day").as("day")
                        .first("channel").as("channel"),
                Aggregation.sort(Sort.Direction.DESC,new String[]{"day","reg_num"}),
                new SkipOperation(pageable.getPageNumber()*pageable.getPageSize()),
                Aggregation.limit(pageable.getPageSize())
        );
        AggregationResults<ChannelDataEntity> ar = mongoTemplate.aggregate(aggregation, "channel_data", ChannelDataEntity.class);
        List<ChannelDataEntity> list = ar.getMappedResults();
        for(ChannelDataEntity ChannelDataEntity:list){
            List<ChannelDataEntity> list3 = mongoTemplate.find(new Query().addCriteria(new Criteria().and("day").is(ChannelDataEntity.getDay()).and("channel").is(ChannelDataEntity.getChannel())), ChannelDataEntity.class);
            if(list3.size()==1){
                ChannelDataEntity.setRetention(list3.get(0).getRetention());
            }

            if(list3.size()>0){
                int[] retention=new int[31];
                for(ChannelDataEntity ChannelDataEntity3:list3){
                    int[] retention1=ChannelDataEntity3.getRetention();
                    for(int i=0;i<retention1.length;i++){
                        retention[i]=retention[i]+retention1[i];
                    }
                }
                ChannelDataEntity.setRetention(retention);
            }

        }

        aggregation = Aggregation.newAggregation(
                match(criteria),
                Aggregation.group("day","channel"),
                Aggregation.group().count().as("total")
        );
        ar = mongoTemplate.aggregate(aggregation, "channel_data", ChannelDataEntity.class);
        long total=0;
        if(ar.getMappedResults().size()>0){
            total = ar.getMappedResults().get(0).getTotal();
        }

        Aggregation aggregation1 = Aggregation.newAggregation(match(criteria),Aggregation.group().sum("reg_num").as("reg_num").sum("charge_amount").as("charge_amount").sum("charge_pnum").as("charge_pnum").sum("new_charge_pnum").as("new_charge_pnum").sum("new_charge_amount").as("new_charge_amount").sum("first_charge_pnum").as("first_charge_pnum"));
        AggregationResults<ChannelDataEntity> ar1 = mongoTemplate.aggregate(aggregation1, "channel_data", ChannelDataEntity.class);
        List<ChannelDataEntity> list1 = ar1.getMappedResults();


        Map map=new HashMap();
        map.put("content",list);
        map.put("totalElements",total);
        map.put("countData",list1);
        return map;
    }

    @Override
   public Map getNobleVip(LostGold lostGold, Pageable pageable){
        Page<LostGold> page = new Page<>(pageable.getPageNumber()+1,pageable.getPageSize());
        QueryWrapper<LostGold> wrapper=new QueryWrapper<>();
        if(lostGold.getQTime()!=null){
            wrapper.ge("time",lostGold.getQTime().get(0).getTime()/1000);
            wrapper.le("time",lostGold.getQTime().get(1).getTime()/1000);
        }
        if(lostGold.getChannel()==null){
            wrapper.eq("channel","total");
        }else{
            wrapper.eq("channel",lostGold.getChannel());
        }
        wrapper.eq("flag","nobleVip");
        wrapper.orderByDesc("time");
        IPage<LostGold> ipage = lostGoldMapper.selectPage(page,wrapper);
        List<LostGold> list = ipage.getRecords();
        String[] xxData=new String[list.size()];
        Map yyDataMaps = new HashMap();
        if(list.size()>0) {
            for (int i = 0; i < list.size(); i++) {
                if(lostGold.getChannel()!=null){
                    list.get(i).setHasChildren(false);
                }
                list.get(i).setTheValue(list.get(i).getLostGold().split("@"));
                xxData[i] = DateUtil.timeStamp2Date(list.get(i).getTime() + "", "yyyy-MM-dd ").trim();
                yyDataMaps.put( (i+1)+"",list.get(i).getLostGold().split("@"));
            }
        }
        Map map=new HashMap();
        map.put("content",list);
        map.put("totalElements",ipage.getTotal());
        map.put("chartData",yyDataMaps);
        map.put("xData",xxData);
        return map;
    }

    @Override
    public List getNobleVipTree(Integer time, String channel, String flag){
        QueryWrapper<LostGold> wrapper=new QueryWrapper<>();
        if(time!=null&&time>0){
            wrapper.eq("time",time);
            wrapper.ne("channel",channel);
            wrapper.eq("flag",flag);
        }
        wrapper.orderBy(true,false,"id");
        List<LostGold> list= lostGoldMapper.selectList(wrapper);
        if(list.size()>0){
            for(LostGold lostGold:list){
                lostGold.setTheValue(lostGold.getLostGold().split("@"));
                lostGold.setHasChildren(false);
            }
        }
        return list;
    }
}
